package com.kay.plugin;


import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.Properties;

/**
 * @Description: 自定义插件   ------ 步骤1 实现Interceptor接口-----
 * @Author: Kay
 * @CreateDate: 2021/6/29$ 12:26$
 * @UpdateUser: Kay
 * @UpdateDate: 2021/6/29$ 12:26$
 */
@Intercepts({
//        @Signature(
//                type = ResultSetHandler.class,
//                method = "handleResultSets",
//                args = {Statement.class}),
        @Signature(
                type = Executor.class,
                method = "query",
                args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) // MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler
        // 可配置多个 @Signature
       /* @Signature(
                type = Executor.class,
                method = "commit",
                args = {boolean.class}) */// 参数类型，防止因为方法重载，找不到具体的方法
})
public class MyPlugin implements Interceptor {
    /**
     * 5. 在代理类执行方法时，会触发invoke(),如果该方法在signatureMap（@Signature）中，将触发此处的 intercept() 方法
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 此处的invocation 在Plugin.invoke方法中，  传入的 new Invocation(target, method, args)
        System.out.println("---------------------------------------  方法已经被增强了，即将要执行原方法");
        return invocation.proceed(); // 原方法继续执行
    }

    /**
     * 1.当 MyPlugin 在 SqlMapConfig.xml中配置在plugin标签中；
     * 2.MyBatis在初始化阶段，XMLConfigBuilder通过加载SqlMapConfig时，会将当前这个过滤器加入到 InterceptorChain中的List<Interceptor> interceptors链路中
     * 3.初始化四大对象的时候，会调用pluginAll(); 调用interceptor.plugin()进入到本方法
     * 4.在本方法中调用Plugin.wrap对为了对目标类（四大对象）创建代理对象
     * @param target
     * @return
     */
    @Override
    public Object plugin(Object target) {
        System.out.println("-------------------------将要对" + target + "进行增强 ------------------------");
        return Plugin.wrap(target, this);// 这一步是为了将目标对象进行包装增强
    }

    @Override
    public void setProperties(Properties properties) {
        System.out.println("-------------------------插件配置的属性值" + properties);
    }
}
